package com.it.service;

import org.elasticsearch.action.delete.DeleteResponse;
import org.elasticsearch.action.get.GetResponse;
import org.elasticsearch.action.index.IndexResponse;
import org.elasticsearch.action.search.SearchRequestBuilder;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.action.search.SearchType;
import org.elasticsearch.action.update.UpdateRequest;
import org.elasticsearch.action.update.UpdateResponse;
import org.elasticsearch.client.transport.TransportClient;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.SearchHit;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cglib.beans.BeanMap;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.concurrent.ExecutionException;

@Service
public class ElasticSearchService {

    @Autowired
    private TransportClient client;

    private static final String INDEX = "book";

    private static final String TYPE = "novel";

    /**
     * @Description:新增
     * @Param: [obj]
     * @return: org.springframework.http.ResponseEntity
     * @Author: gejianhao
     * @date: 2019/7/29
     */
    public String add(Object obj) {
        IndexResponse indexResponse = this.client.prepareIndex(INDEX, TYPE).setId("99").setSource(convert2Map(obj)).get();
        return indexResponse.getId();
    }

    /**
     * @Description: 根据主键查询详情
     * @Param: [id]
     * @return: java.lang.Object
     * @Author: gejianhao
     * @date: 2019/7/29
     */
    public Object queryById(String id) {
        GetResponse result = this.client.prepareGet(INDEX, TYPE, id).get();
        return result.getSource();
    }

    /**
     * @Description: 描述
     * @Param: []
     * @return: java.lang.String
     * @Author: gejianhao
     * @date: 2019/7/29
     */
    public String delete(String id) {
        DeleteResponse delete = this.client.prepareDelete(INDEX, TYPE, id).get();
        return delete.getId();
    }


    /**
     * @Description:修改
     * @Param: [id, obj]
     * @return: java.lang.String
     * @Author: gejianhao
     * @date: 2019/7/29
     */
    public String update(String id, Object obj) throws InterruptedException, ExecutionException {
        UpdateRequest update = new UpdateRequest(INDEX, TYPE, id);
        update.doc(convert2Map(obj));
        UpdateResponse updateBuilder = this.client.update(update).get();
        return updateBuilder.getId();
    }

    /**
     * @Description:
     * @Param: []
     * @return: org.springframework.http.ResponseEntity
     * @Author: gejianhao
     * @date: 2019/7/29
     */
    public List<Map<String, Object>> boolquery(int currentPage, int pageSize) {
        BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();// 设置聚合查询
        boolQuery.must(QueryBuilders.matchQuery("name", "姓"));
//        RangeQueryBuilder rangQuery = QueryBuilders.rangeQuery("age").from(10);//范围查询
//        rangQuery.to(200);//小于
//        boolQuery.filter(rangQuery);
        SearchRequestBuilder builder = this.client.prepareSearch(INDEX).setTypes(TYPE).setSearchType(SearchType.DFS_QUERY_THEN_FETCH).setQuery(boolQuery).setFrom(currentPage * pageSize).setSize(pageSize);
        SearchResponse response = builder.get();
        List<Map<String, Object>> list = new ArrayList<>();
        for (SearchHit s : response.getHits()) {
            s.getSource().put("id",s.getId().toString());
            list.add(s.getSource());
        }
        return list;
    }

    /**
     * @Description:
     * @Param: [obj]
     * @return: java.util.Map<java.lang.String, java.lang.Object>
     * @Author: gejianhao
     * @date: 2019/7/29
     */
    public static Map<String, Object> convert2Map(Object obj) {
        Map<String, Object> map = null;
        if (obj != null) {
            BeanMap beanMap = BeanMap.create(obj);
            map = new HashMap<>(beanMap.keySet().size());
            for (Object key : beanMap.keySet()) {

                Object value = beanMap.get(key);

                if (value != null && isLongType(value)) {
                    map.put(key.toString(), value.toString());
                } else if (value != null && isDateType(value)) {
                    map.put(key.toString(), ((Date) value).getTime());
                } else {
                    map.put(key.toString(), value);
                }


            }
        }
        return map;
    }

    public static boolean isLongType(Object obj) {

        if (obj instanceof Long || obj.getClass() == Long.TYPE) {
            return true;
        }
        return false;
    }

    public static boolean isDateType(Object obj) {

        if (obj instanceof Date) {
            return true;
        }
        return false;
    }
}
